<?php
namespace Service\WebSocketService\WebSocketRouter;
use Service\BaseService;
use App\Model\CommodityModel\CommodityArchives;
use Hyperf\DbConnection\Db;
use Service\Code\Normal;

/**
 * 商品主资料导出
 * @author huj
 */
class GoodsListSocketService extends BaseService
{
    public $server;
    public $fd;
    public $host;
    public $pageLimit      = 2000;
    public $percent_status = [
        '1' => '写入中',
        '2' => '完成',
        '3' => '异常错误',
    ];
    
    /**
     * 业务方法
     * @param object $server
     * @param int $fd
     * @param array $data
     * @param array $sysInfo
     * @param array $excel_hedaer
     * @param array $excel_data
     * @return mixed
     */
    public function goodsExport($server,int $fd,array $data,array $sysInfo,array $excel_hedaer,array $excel_data) 
    {
        $this->server   = $server;
        $this->fd       = $fd;

        //开始处理业务逻辑
        $send = Normal::returnWsStatus(Normal::WS_START, "进行中，开始处理业务逻辑!", [
            'percent' => 0.03,
        ]);
        $server->push($fd,json_encode($send,JSON_UNESCAPED_UNICODE));
        
        //获取总条数
        $total_count = $this->getQuery($data)->count();
        //预估分页
        $total_page  = ceil($total_count / $this->pageLimit);
        $importData  = [];
        
        //导出数据
        $lastId = 0;
        $page = 1;
        while ( true ) 
        {
            $rows = $this
            ->getQuery($data)
            ->select($this->getFields())
            ->where('g.ID','>',$lastId)
            ->orderBy('g.ID','asc')
            ->limit($this->pageLimit)
            ->get()
            ->toArray();
            if( empty($rows)) 
            {
                break;
            }
            
            //处理无极分页
            $endRow = end($rows);
            $lastId = $endRow['ID'];
            
            if ($rows)
            {
                $tmpData = [];
                foreach ($rows as $goods)
                {
                    $goods_type_text = CommodityArchives::instance()->goods_types[$goods['goods_type']] ?? '未定义';
                    $weight_kg       = CommodityArchives::instance()->weight_unit[$goods['WeightUnit']] ?? '未定义';
                    $tmpData[] = [
                        $goods['name'],
                        $goods['sku_code'],
                        $goods['bar_code'],
                        $goods_type_text,
                        $goods['brand_name'] ?: '',
                        $goods['first_class_name'] ?: '',
                        $goods['second_class_name'] ?: '',
                        $goods['third_class_name'] ?: '',
                        $goods['country_name'] ?: '',
                        $goods['unit_name'] ?: '',
                        $goods['market_price'],
                        $weight_kg,
                    ];
                }
                
                $importData = array_merge($importData, $tmpData);
            }
            
            if ($page == $total_page) {
                $percent = 98.00; //预留给写文件使用
            } else {
                $percent = bcdiv($page, $total_page, 4);
                $percent = bcmul($percent, 100, 2);
                $percent = $percent > 98.0 ? 97.99: $percent;
            }
            
            if ($this->server) {
                $send = Normal::returnWsStatus(Normal::WS_START, "进行中", [
                    'percent' => $percent,
                ]);
                $send = json_encode($send, JSON_UNESCAPED_UNICODE);
                $this->server->push($this->fd, $send);
            }   
            
            $page++;
        }
        
        //组装数据完成
        $send = Normal::returnWsStatus(Normal::WS_START, "进行中", [
            'percent' => 99.00,
        ]);
        $this->server->push($this->fd,json_encode($send, JSON_UNESCAPED_UNICODE));
        
        //开始导出数据
        $result_export = \exportFile($this->getHeader(),$importData,'商品主资料导出');
        
        $importData = [];
        //导出异常
        if( $result_export['code'] != Normal::SUC ) {
            return Normal::returnWsStatus(Normal::WS_ERROR, $result_export['msg']);
        }
        
        return Normal::returnWsStatus(Normal::WS_END, "已完成", [
            'percent'      => 100.00,
            'download_url' => $result_export['data']['url'],
        ]);
    }
    
    /**
     * 获取查询条件
     * @param array $data
     */
    public function getQuery(array $data)
    {
        $table = CommodityArchives::instance()->getTable();
        $model = CommodityArchives::instance()
        ->from("{$table} as g")
        ->leftJoin('brandinfo_s2b as b', "b.ID","=","g.BrandID")
        ->leftJoin('classifyinfo_s2b as c', "c.ID","=","g.FirstClassificationID")
        ->leftJoin('classifyinfo_s2b as cl', "cl.ID","=","g.SecondClassificationID")
        ->leftJoin('classifyinfo_s2b as cla', "cla.ID","=","g.ThirdClassificationID")
        ->leftJoin('countryinfo_s2b as co', "co.ID","=","g.CountryID")
        ->leftJoin('unitinfo_s2b as u', "u.ID","=","g.UnitID");
        
        if (isset($data['id']) && !empty($data['id'])) {
            $model = $model->where('g.ID', $data['id']);
        }
        if (isset($data['name']) && !empty($data['name'])) {
            $model = $model->whereLike('g.Name', '%' . $data['name'] . '%');
        }
        if (isset($data['sku_code']) && !empty($data['sku_code'])) {
            $model = $model->where('g.SKUCode', $data['sku_code']);
        }
        if (isset($data['bar_code']) && !empty($data['bar_code'])) {
            $model = $model->where('g.BarCode', $data['bar_code']);
        }
        if (isset($data['is_forbidden']) && in_array($data['is_forbidden'], [0, 1], true)) {
            $model = $model->where('g.IsForbidden', $data['is_forbidden']);
        }
        if (isset($data['class_ids']) && !empty($data['class_ids']))
        {
            $model = $model->where(function($query) use ($data)
            {
                $query
                ->whereIn('g.FirstClassificationID', $data['class_ids'])
                ->orWhere('g.SecondClassificationID','in', $data['class_ids'])
                ->orWhere('g.ThirdClassificationID','in', $data['class_ids']);
            });
        }
        if (isset($data['brand_ids']) && !empty($data['brand_ids'])) {
            $model = $model->whereIn('g.BrandID', $data['brand_ids']);
        }
        
        if (isset($data['country_ids']) && !empty($data['country_ids'])) {
            $model = $model->whereIn('g.CountryID', $data['country_ids']);
        }
        
        if (isset($data['is_complete']) && in_array($data['is_complete'], [0, 1], true)) {
            $model = $model->where('g.IsIntegrity', $data['is_complete']);
        }
        
        if (isset($data['goods_type']) && in_array($data['goods_type'], [0, 1, 2], true)) {
            $model = $model->where('g.CommodityType', $data['goods_type']);
        }
        
        if (isset($data['is_market_price']) && in_array($data['is_market_price'], [0, 1], true)) {
            if ($data['is_market_price'] == Goods::IS_MARKET_PRICE_NO) {
                $model = $model->where('g.MarketPrice', 0);
            } else {
                $model = $model->where('g.MarketPrice', '>', 0);
            }
        }
        return $model;
    }
    
    /**
     * 获取字段
     */
    public function getFields()
    {
        return [
            Db::raw('g.ID as ID'),
            Db::raw('g.Name as name'),
            Db::raw('g.SKUCode as sku_code'),
            Db::raw('g.BarCode as bar_code'),
            Db::raw('g.CommodityType as goods_type'),
            Db::raw("IFNULL(b.BrandName, '') as brand_name"),
            Db::raw("IFNULL(c.ClassificationName, '') as first_class_name"),
            Db::raw("IFNULL(cl.ClassificationName, '') as second_class_name"),
            Db::raw("IFNULL(cla.ClassificationName, '') as third_class_name"),
            Db::raw("IFNULL(co.CountryName, '') as country_name"),
            Db::raw("IFNULL(u.Name, '') as unit_name"),
            Db::raw('g.MarketPrice as market_price'),
            Db::raw('g.Weight as weight'),
            Db::raw('g.WeightUnit')
        ];
    }
    
    /**
     * 获取头部
     */
    public function getHeader() 
    {
        return [
            '商品名称',
            '自编码',
            '国际条形码',
            '商品类型',
            '品牌',
            '一级分类',
            '二级分类',
            '三级分类',
            '原产国',
            '单位',
            '市场价',
            '重量(kg)',
        ];
    }
}